package org.xp.judgeplatform.controller;

import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.embedding.EmbeddingRequest;
import org.springframework.ai.embedding.EmbeddingResponse;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import org.xp.judgeplatform.common.ApiResponse;
import org.xp.judgeplatform.converter.ChatConverter;
import org.xp.judgeplatform.pojo.dto.ChatDTO.ChatSendMessageDTO;
import org.xp.judgeplatform.pojo.entity.ChatMessage;
import org.xp.judgeplatform.pojo.entity.ChatSession;
import org.xp.judgeplatform.pojo.vo.ChatVO.ChatMessageVO;
import org.xp.judgeplatform.pojo.vo.ChatVO.ChatSessionVO;
import org.xp.judgeplatform.security.UserPrincipal;
import org.xp.judgeplatform.service.ChatService;
import reactor.core.publisher.Flux;

import java.util.List;
import java.util.UUID;

import static org.springframework.ai.chat.memory.ChatMemory.CONVERSATION_ID;

@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/ai")
@CrossOrigin(origins = {"http://localhost:5173", "http://localhost:3000"})
public class ChatController {

    private final ChatClient chatClient;
    private final ChatService chatService;
    private final ChatConverter chatConverter;
    private final EmbeddingModel embeddingModel;

    /**
     * 流式聊天接口
     * 支持实时AI对话，返回流式响应
     * 
     * @param sendMessageDTO 发送消息的请求参数
     * @return 流式AI响应内容
     */
    @PostMapping(value = "/chat", produces = MediaType.TEXT_PLAIN_VALUE + ";charset=UTF-8")
    public Flux<String> chat(@Valid @RequestBody ChatSendMessageDTO sendMessageDTO) {
        log.info("收到聊天请求: 用户ID={}, 会话ID={}, 内容={}",
                sendMessageDTO.getUserId(), sendMessageDTO.getSessionId(), sendMessageDTO.getContent());

        try {
            // 如果没有会话ID，自动生成一个
            if (sendMessageDTO.getSessionId() == null || sendMessageDTO.getSessionId().trim().isEmpty()) {
                String newSessionId = UUID.randomUUID().toString();
                sendMessageDTO.setSessionId(newSessionId);
                log.info("自动生成会话ID: {}", newSessionId);
            }

            // 发送消息（自动创建会话或追加到现有会话）
            String sessionId = chatService.sendMessage(sendMessageDTO);

            // 用于收集AI完整响应
            StringBuilder fullResponse = new StringBuilder();

            // 返回流式响应
            return chatClient.prompt(sendMessageDTO.getContent())
                    .advisors(a -> a.param(CONVERSATION_ID, sessionId))
                    .stream()
                    .content()
                    .map(content -> {
                        // TRACE级别：流式响应的每个片段（过于频繁，生产环境不记录）
                        fullResponse.append(content);
                        return content;
                    })
                    .doOnComplete(() -> {
                        // 流结束后保存AI的完整回复
                        if (!fullResponse.isEmpty()) {
                            chatService.saveAIReply(sessionId, fullResponse.toString());
                            log.info("AI回复已保存: sessionId={}, 内容长度={}", sessionId, fullResponse.length());
                        }
                    })
                    .doOnError(error -> log.error("处理AI响应时发生错误: {}", error.getMessage(), error));

        } catch (Exception e) {
            log.error("聊天请求处理失败: {}", e.getMessage(), e);
            return Flux.just("抱歉，服务暂时不可用，请稍后重试。");
        }
    }
    
    /**
     * 获取指定用户的会话列表
     * 返回用户的所有活跃会话，按创建时间倒序排列
     * 
     * @param userId 用户ID
     * @return 会话列表的API响应
     */
    @GetMapping("/sessions/{userId}")
    public ApiResponse<List<ChatSessionVO>> getUserSessions(
            @PathVariable Integer userId, Authentication authentication) {
        try {
            UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
            if (!principal.getId().equals(userId)) {
                return ApiResponse.error("无权查看其他用户的会话");
            }

            log.info("获取用户会话列表: userId={}", userId);
            List<ChatSession> sessions = chatService.getUserSessions(userId);
            List<ChatSessionVO> sessionVOs = chatConverter.toChatSessionVOList(sessions);
            return ApiResponse.success(sessionVOs);
        } catch (Exception e) {
            log.error("获取会话列表失败: userId={}, error={}", userId, e.getMessage(), e);
            return ApiResponse.error("获取会话列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取指定会话的消息列表
     * 返回会话中的所有消息，按创建时间正序排列
     * 
     * @param sessionId 会话ID
     * @return 消息列表的API响应
     */
    @GetMapping("/sessions/{sessionId}/messages")
    public ApiResponse<List<ChatMessageVO>> getSessionMessages(@PathVariable String sessionId) {
        try {
            log.info("获取会话消息列表: sessionId={}", sessionId);
            List<ChatMessage> messages = chatService.getSessionMessages(sessionId);
            List<ChatMessageVO> messageVOs = chatConverter.toChatMessageVOList(messages);
            return ApiResponse.success(messageVOs);
        } catch (Exception e) {
            log.error("获取消息列表失败: sessionId={}, error={}", sessionId, e.getMessage(), e);
            return ApiResponse.error("获取消息列表失败: " + e.getMessage());
        }
    }

    /**
     * 删除指定会话
     * 删除会话及其所有相关消息，包含权限验证
     * 
     * @param sessionId 会话ID
     * @param userId 用户ID，用于权限验证
     * @return 删除结果的API响应
     */
    @DeleteMapping("/sessions/{sessionId}")
    public ApiResponse<Void> deleteSession(
            @PathVariable String sessionId,
            @RequestParam Integer userId, Authentication authentication) {
        try {
            UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
            if (!principal.getId().equals(userId)) {
                return ApiResponse.error("无权删除其他用户的会话");
            }

            log.info("删除会话: sessionId={}, userId={}", sessionId, userId);
            chatService.deleteSession(sessionId, userId);
            return ApiResponse.success(null, "会话删除成功");
        } catch (Exception e) {
            log.error("删除会话失败: sessionId={}, userId={}, error={}", sessionId, userId, e.getMessage(), e);
            return ApiResponse.error("删除会话失败: " + e.getMessage());
        }
    }

    @GetMapping("/embedding")
    public EmbeddingResponse embedding(@RequestParam String text) {
        return embeddingModel.call(
                new EmbeddingRequest(List.of(text),
                        DashScopeEmbeddingOptions.builder().withModel("text-embedding-v3").build())
        );
    }
}
